# coding:utf-8

import logging

from . import api
from iHome import redis_store, db
from iHome.utils import constants
from iHome.utils.response_code import RET
from iHome.utils.captcha.pic_store import pic_store
from iHome.models import Area, House, Order, Facility, User, HouseImage
from flask import current_app, jsonify, session, request, g
from iHome.utils.commons import login_required
from datetime import datetime


@api.route('/houses', methods=['POST'])
@login_required
def publish_house():
    """发布房源"""
    # 获取当前用户id(检测当前用户登录状态）
    user_id = g.user_id
    # 获取参数
    title = request.json.get('title')
    price = request.json.get('price')
    area_id = request.json.get('area_id')
    address = request.json.get('address')
    room_count = request.json.get('room_count')
    acreage = request.json.get('acreage')
    unit = request.json.get('unit')
    capacity = request.json.get('capacity')
    beds = request.json.get('beds')
    deposit = request.json.get('deposit')
    min_days = request.json.get('min_days')
    max_days = request.json.get('max_days')
    if not all(
            [title, price, address, area_id, room_count, acreage, unit, capacity, beds, deposit, min_days, max_days]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数不足')
    if min_days > max_days:
        return jsonify(errno=RET.DATAERR, errmsg="最少入住时间必须不能大于最多入住时间")
    # 创建房屋对象
    house = House()
    house.user_id = user_id
    house.title = title
    house.price = price
    house.area_id = area_id
    house.address = address
    house.room_count = room_count
    house.acreage = acreage
    house.unit = unit
    house.capacity = capacity
    house.beds = beds
    house.deposit = deposit
    house.min_days = min_days
    house.max_days = max_days

    # 设置设施信息
    facility = request.json.get('facility')
    if facility:
        facilities = Facility.query.filter(Facility.id.in_(facility)).all()
        house.facilities = facilities

    # 提交房屋对象到数据库
    try:
        db.session.add(house)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg='房屋信息储存失败')

    # 返回数据
    data = {
        'house_id': house.id
    }
    return jsonify(errno=RET.OK, errmsg='房源发布成功', data=data)


@api.route('/houses/<int:house_id>/images', methods=['POST'])
@login_required
def upload_house_pic(house_id):
    """
    上传房源图片
    :param house_id: 房源id
    :return:
    """

    # 取到图片文件
    image_file = request.files.get('house_image')
    if not image_file:
        return jsonify(errno=RET.PARAMERR, errmsg="未选择图片")

    # 尝试查询房屋数据
    try:
        house = House.query.filter_by(id=house_id).first()
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询房屋数据失败')
    if not house:
        return jsonify(errno=RET.NODATA, errmsg='未查询到对应房屋')

    # 使用七牛上传图片
    image_data = image_file.read()
    try:
        image_name = pic_store(image_data)
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.THIRDERR, errmsg="上传图片到七牛失败")

    # 判断房屋是否有主图片，如果没有，则设置
    if not house.index_image_url:
        house.index_image_url = image_name
        db.session.add(house)

    # 生成房屋图片模型并保存至数据数据库
    house_image = HouseImage()
    house_image.house_id = house_id
    house_image.url = image_name

    try:
        db.session.add(house_image)
        db.session.commit()
    except Exception as e:
        logging.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg="保存房屋图片失败")

    # 返回数据
    image_url = constants.QINIU_DOMIN_PREFIX + image_name
    return jsonify(errno=RET.OK, errmsg='OK', data={'url': image_url})


# 房屋详情页视图
@api.route("/houses/<int:house_id>")
def get_house_detail(house_id):
    """
    1. 通过房屋的id查询出指定的房屋
    2. 将房屋的相关数据进行返回
    3. 考虑是否缓存的问题
    :param house_id:
    :return:
    """

    # 先尝试从redis中去取
    # 获取当前登录用户的Id,如果没有登录,那么就返回-1
    user_id = session.get("user_id", -1)
    try:
        house_dict = redis_store.get(("house_detail_%d" % house_id))
        # 如果有数据,直接返回
        if house_dict:
            return jsonify(errno=RET.OK, errmsg="OK", data={"user_id": user_id, "house": eval(house_dict)})
    except Exception as e:
        current_app.logger.error(e)

    # 从Mysql 数据库中查询数据
    try:
        house = House.query.get(house_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="数据查询错误")

    if not house:
        return jsonify(errno=RET.NODATA, errmsg="房屋不存在")

    house_dict = house.to_full_dict()

    # 缓存当前房屋数据
    try:
        redis_store.set(("house_detail_%d" % house_id), house_dict, constants.HOUSE_DETAIL_REDIS_EXPIRE_SECOND)
    except Exception as e:
        current_app.logger.error(e)
    return jsonify(errno=RET.OK, errmsg="OK", data={"user_id": user_id, "house": house.to_full_dict()})


@api.route('/areas')
def get_areas_info():
    """城区查询视图"""
    areas = None  # type:Area
    try:
        areas = Area.query.all()
    except Exception as err:
        current_app.logger.error(err)
        return jsonify(errno=RET.DBERR, errmsg="城区查询错误")
    area_list = []
    for area in areas:
        area_list.append(area.to_dict())
    return jsonify(errno=RET.OK, errmsg="获取成功", data=area_list)


@api.route('/houses/index')
def house_index():
    """首页轮播图"""
    # 从数组库中加载数据
    try:
        houses = House.query.order_by(House.order_count.desc()).limit(constants.HOME_PAGE_MAX_HOUSES).all()
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据查询失败')

    # 如果数据库中没有数据
    if not houses:
        return jsonify(errno=RET.NODATA, errmsg='未查询到数据')

    # 拼接到数组中
    houses_dict = []
    for house in houses:
        houses_dict.append(house.to_basic_dict())
    # 返回数据
    return jsonify(errno=RET.OK, errmsg='OK', data=houses_dict)


@api.route("/houses")
def get_houses_list():
    """查询房屋信息"""
    # 获取地区id值
    aid = request.args.get("aid", "")
    # 获取排序要求
    sk = request.args.get("sk", "new")
    # 获取需求页数
    p = request.args.get("p", 1)
    # 获取入住日期
    start_date_str = request.args.get("sd", "")  # 开始入住日期
    end_date_str = request.args.get("ed", "")  # 结束入住时间
    start_datetime = None
    end_datetime = None
    # 判断日期参数
    try:
        if start_date_str:
            start_datetime = datetime.strptime(start_date_str, "%Y-%m-%d")
        if end_date_str:
            end_datetime = datetime.strptime(end_date_str, "%Y-%m-%d")
        if start_date_str and end_date_str:
            assert start_datetime < end_datetime, Exception("结束时间要大于开始时间")
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg="参数错误")

    try:
        if aid != '':
            aid = int(aid)
        else:
            pass
    except Exception as e:
        current_app.logger.error(e)
    try:
        p = int(p)
    except Exception as e:
        current_app.logger.error(e)
    # 查询条件列表
    filter_list = []
    # 日期查询条件,查询选择日期内已被预订的房间
    order_houses = []
    if start_datetime and end_datetime:
        order_houses = Order.query.filter(Order.begin_date < end_datetime, Order.end_date > start_datetime).all()
    elif start_datetime:
        order_houses = Order.query.filter(Order.end_date > start_datetime).all()
    elif end_datetime:
        order_houses = Order.query.filter(Order.begin_date < end_datetime).all()

    if order_houses:
        # 如果被预定取出房屋id
        order_id_list = [order.house_id for order in order_houses]
        # 添加过滤条件, 不包含冲突房屋id
        filter_list.append(House.id.notin_(order_id_list))
    # 地区查询条件
    if aid:
        filter_list.append(House.area_id == aid)
    # 查询房屋信息
    try:
        # paginate()分页方法,参数1:当前页码 参数2:每一页多少数据,参数3:异常抛出,false不抛出,true抛出
        if sk == "booking":
            paginate = House.query.filter(*filter_list).order_by(House.order_count.desc()).paginate(p, constants.HOUSE_LIST_PAGE_CAPACITY, False)
        elif sk == "price-inc":
            paginate = House.query.filter(*filter_list).order_by(House.price).paginate(p, constants.HOUSE_LIST_PAGE_CAPACITY, False)
        elif sk == "price-des":
            paginate = House.query.filter(*filter_list).order_by(House.price.desc()).paginate(p, constants.HOUSE_LIST_PAGE_CAPACITY, False)
        else:
            paginate = House.query.filter(*filter_list).order_by(House.create_time.desc()).paginate(p, constants.HOUSE_LIST_PAGE_CAPACITY, False)
        # 获取当前页面房屋信息
        houses = paginate.items
        # 获取总页数
        total_page = paginate.pages
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="房屋信息查询异常")

    houses_dict = []
    for house in houses:
        houses_dict.append(house.to_basic_dict())

    data = {"houses": houses_dict, "total_page": total_page}
    # 保存缓存到数据库
    try:
        redis_key = "house_list_%s_%s_%s_%s" % (start_date_str, end_date_str, aid, sk)
        # 把文件以整页保存到数据库
        redis_store.hset(redis_key, p, data)
        # 设置过期时间
        redis_store.expire(redis_key, constants.HOUSE_LIST_REDIS_EXPIRES)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="保存数据异常")
    return jsonify(errno=RET.OK, errmsg="获取成功", data=data)


# 我的房屋列表
@api.route('/user/houses', methods=['GET'])
@login_required
def publish_list():
    """我的房屋列表显示接口"""
    user_id = g.user_id
    # 获取当前用户信息
    user = None  # type:User
    try:
        user = User.query.filter(User.id == user_id).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据库查询错误')

    # 获取当前用户发布的房屋id列表
    house_id_list = user.houses

    data = []
    # 遍历获取各房屋信息，并添加到我的房屋列表
    for house_obj_id in house_id_list if house_id_list else []:
        house = None  # type:House
        try:
            house = House.query.filter(House.id == house_obj_id.id).first()
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg='数据库查询错误')

        # 获取当前房屋所在城区对象
        area = None  # type:Area
        try:
            area = Area.query.filter(Area.id == house.area_id).first()
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg='数据库查询错误')

        house_info = {
            'address': house.address,
            'area_name': area.name,
            'ctime': house.create_time,
            'house_id': house.id,
            'img_url': constants.QINIU_DOMIN_PREFIX + house.index_image_url,
            'order_count': house.order_count,
            'price': house.price,
            'room_count': house.room_count,
            'title': house.title,
            'user_avatar': user.avatar_url
        }
        data.append(house_info)

    # 返回我的房屋发布列表数据
    return jsonify(errno=RET.OK, errmsg='成功', data=data)
